package j.framework.core;

import j.data.ActionMessage;
import j.data.ActionResult;
import j.util.*;
import j.util.jdbc.JdbcTemplate;
import j.util.jdbc.QueryJdbcTemplate;
import j.util.jdbc.TransactionalJdbcTemplate;
import j.util.jdbc.simple.annotation.Column;
import j.util.jdbc.simple.annotation.DataType;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Time;
import java.util.Date;
import java.util.List;

/**
 * 业务层上下文
 * User: jason
 * Date: 2014/11/10 10:03
 */
public class ServiceContext implements Serializable {
    //操作结果实例
    public final ActionResult actionResult = ActionResult.New();
    public boolean hasErrors(){
        return actionResult.hasErrors();
    }
    public String getErrorMessages(){
        if(this.hasErrors()){
            //有错误,生成错误列表
            List<ActionMessage> errs = actionResult.toList();
            StringBuilder s = new StringBuilder("");
            int i = 1;
            for(ActionMessage e : errs){
                s.append(i++).append(".").append(e.getMessage()).append("\\n");
            }
            return s.toString();
        }
        return null;
    }
    //所有参数封装在这里
    public final JMap params = New.jmap();   //原始参数，没有加工处理

    private SysLog log;

    public SysLog getLog() {
        return log;
    }
    public void setLog(SysLog log) {
        this.log = log;
    }

    public String getDesId(String key){
        return DES.decrypt(params.getString(key));
    }

    private LoginUser user;

    public ServiceContext(LoginUser user) {
        this.user = user;
    }

    private boolean logSupported;

    public boolean isLogSupported() {
        return logSupported;
    }
    public void setLogSupported(boolean logSupported) {
        this.logSupported = logSupported;
    }

    /**
     * 获取当前登录对象
     * @return
     */
    public LoginUser getUser(){
        return user;
    }

    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
        this.jdbcTemplate = jdbcTemplate;
    }

    public JdbcTemplate getJdbcTemplate(){
        return jdbcTemplate;
    }

    public QueryJdbcTemplate getQueryJdbcTemplate(){
        if(jdbcTemplate instanceof QueryJdbcTemplate){
            return (QueryJdbcTemplate)jdbcTemplate;
        }
        throw new RuntimeException("请检测此方法是否支持【查询类JDBC模板】！");
    }
    public TransactionalJdbcTemplate getTransactionalJdbcTemplate(){
        if(jdbcTemplate instanceof TransactionalJdbcTemplate){
            return (TransactionalJdbcTemplate)jdbcTemplate;
        }
        throw new RuntimeException("请检测此方法是否支持【事务类JDBC模板】！");
    }

    public boolean inTransaction(){
        return jdbcTemplate instanceof TransactionalJdbcTemplate;
    }

    private Object bean = null;

    /**
     * 从参数中抽取出来实体类
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> T getBean(Class<T> clazz){
        if(bean != null){
            return (T)bean;
        }
        try{
            bean = clazz.newInstance();
        }catch(Exception e){
            throw new RuntimeException(String.format("实体类%s不存在。", clazz.getName()));
        }
        Object v;
        String setMethodName,displayName,parameterValue,str;

        Column $column;
        Field[] fields = clazz.getDeclaredFields();
        DataType dataType;
        int i;
        double d;
        float fl;
        long l;
        short s;
        boolean needDes = false;
        for(Field f : fields){
            //把值从请求中取出来
            //如果请求中不存在此参数，则直接忽略
            if(!params.containsKey(f.getName())){
                continue;
            }
            needDes = false;
            parameterValue = params.getString(f.getName());
            displayName = f.getName();
            $column = f.getAnnotation(Column.class);
            v = null;
            if($column!=null){
                if($column.needDes()){
                    v = parameterValue;
                    needDes = true;
                }else {
                    //按给定的值进行验证数字的正确性
                    displayName = $column.displayName();
                    if (StringUtils.isNullOrEmpty(displayName)) {
                        displayName = f.getName();
                    }
                    //在给定的参数值不为空时检测数据类型是否有误
                    if (StringUtils.isNotEmpty(parameterValue)) {
                        v = parseBeanValue(f, parameterValue, displayName);
                    }
                    //检测值的必填项
                    if (!$column.nullable()) {
                        //要求此字段必须有值
                        if (StringUtils.isNullOrEmpty(parameterValue)) {
                            actionResult.add(String.format("请输入[%s]项！", displayName));
                            continue;
                        }
                    }
                    //检测值的取值范围
                    if ($column.min() > Integer.MIN_VALUE && v != null) {
                        //用户指定了最小值
                        if (v instanceof String) {
                            str = (String) v;
                            if (str.length() < $column.min()) {
                                actionResult.add(String.format("[%s]的长度必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        } else if (v instanceof Integer) {
                            i = (Integer) v;
                            if (i < $column.min()) {
                                actionResult.add(String.format("[%s]的值必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        } else if (v instanceof Float) {
                            fl = (Float) v;
                            if (fl < $column.min()) {
                                actionResult.add(String.format("[%s]的值必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        } else if (v instanceof Double) {
                            d = (Double) v;
                            if (d < $column.min()) {
                                actionResult.add(String.format("[%s]的值必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        } else if (v instanceof Long) {
                            l = (Long) v;
                            if (l < $column.min()) {
                                actionResult.add(String.format("[%s]的值必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        } else if (v instanceof Short) {
                            s = (Short) v;
                            if (s < $column.min()) {
                                actionResult.add(String.format("[%s]的值必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        }
                    }
                    if ($column.max() < Integer.MAX_VALUE && v != null) {
                        //用户指定了最大值
                        if (v instanceof String) {
                            str = (String) v;
                            if (str.length() > $column.max()) {
                                actionResult.add(String.format("[%s]的长度必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        } else if (v instanceof Integer) {
                            i = (Integer) v;
                            if (i > $column.max()) {
                                actionResult.add(String.format("[%s]的值必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        } else if (v instanceof Float) {
                            fl = (Float) v;
                            if (fl > $column.max()) {
                                actionResult.add(String.format("[%s]的值必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        } else if (v instanceof Double) {
                            d = (Double) v;
                            if (d > $column.max()) {
                                actionResult.add(String.format("[%s]的值必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        } else if (v instanceof Long) {
                            l = (Long) v;
                            if (l > $column.max()) {
                                actionResult.add(String.format("[%s]的值必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        } else if (v instanceof Short) {
                            s = (Short) v;
                            if (s > $column.max()) {
                                actionResult.add(String.format("[%s]的值必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        }
                    }
                    if(StringUtils.isNotEmpty(parameterValue)) {
                        //只有在不为空时，才验证这些数据类型是否正确
                        dataType = $column.datatype();
                        if (dataType.equals(DataType.EMAIL)) {
                            actionResult.isValidEmail(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的电子邮件格式，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.MOBILE)) {
                            actionResult.isValidMobile(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的手机格式，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.TELEPHONE)) {
                            actionResult.isValidTelephone(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的电话格式，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.PHONE)) {
                            actionResult.isValidPhone(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的电话格式，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.URL)) {
                            actionResult.isValidURL(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的网址格式，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.ZipCode)) {
                            actionResult.isValidZip(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的邮政编码，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.CHINESE)) {
                            actionResult.isValidChinese(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的中文字符，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.IDCARD)) {
                            actionResult.isValidIdentityCard(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的身份证号，请重新输入！", displayName));
                        }
                    }
                }
            }else{
                v = parseBeanValue(f,parameterValue,displayName);
            }
            if(v!=null){
                setMethodName = "set"+Character.toUpperCase(f.getName().charAt(0))+f.getName().substring(1);
                try {
                    Method m = clazz.getDeclaredMethod(setMethodName,f.getType());
                    if(needDes){
                        v = DES.decrypt((String) v);
                    }
                    m.invoke(bean,v);
                } catch (Exception e) {
                    actionResult.add(String.format("[%s]的值输入有错，请输入正确的类型！",displayName));
                }
            }
        }
        return (T)bean;
    }

    private Object parseBeanValue(Field f,String parameterValue,String displayName) {
        Object v = null;
        try {
            if(f.getType().equals(Date.class)){
                String dateFormat = "yyyy-MM-dd";
                String[] arr = parameterValue.split(":");
                if(arr.length == 1){
                    //再检测一下有没有小时
                    arr = parameterValue.split("\\s");
                    if(arr.length == 2){
                        //仅有小时，没有分及秒
                        dateFormat += " HH";
                    }
                }else if(arr.length == 2){
                    //有小时，有分，但没有秒
                    dateFormat += " HH:mm";
                }else if(arr.length == 3){
                    //有小时，有分，也有秒
                    dateFormat += " HH:mm:ss";
                }
                v = DateUtils.toDate(parameterValue, dateFormat);
            }else if(f.getType().equals(Time.class)){
                if(StringUtils.isNotEmpty(parameterValue)){
                    String[] arr = parameterValue.split(":");
                    String vv = parameterValue;
                    if(arr.length == 2){
                        vv += ":00";
                    }
                    v = Time.valueOf(vv);
                }
            }else{
                v = org.apache.commons.beanutils.ConvertUtils.convert(parameterValue, f.getType());
            }
        }catch (Exception e){
            actionResult.add(String.format("[%s]的值输入有错，请输入正确的类型！",displayName));
        }
        return v;
    }
}
